import datetime
import json
import time

import numpy as np
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt

from stock.models import StockDetail, Stock
from .model_definition import RNN, LSTM
from utils.stock_data_util import StockDataUtil
import torch


import xlwt
import xlrd
from snownlp import SnowNLP

def predict_stock(code, w_lstm, w_nlp, w_srl):
    if StockDetail.objects.filter(code=code,
                                  date=time.strftime("%Y-%m-%d", time.localtime(time.time() - 86400))).count() == 0:
        StockDetail.objects.all().delete()
        print("正在获取股票详细数据")
        stock_data = StockDataUtil.get_stock_data_from_code(code=code, k=20)
        for i in range(len(stock_data)):
            # 日期,开盘,收盘,最高,最低,成交量,成交额,振幅,涨跌幅,涨跌额,换手率
            date = stock_data["日期"][i]
            open = stock_data["开盘"][i]
            close = stock_data["收盘"][i]
            high = stock_data["最高"][i]
            low = stock_data["最低"][i]
            turnover = stock_data["成交量"][i]
            volume = stock_data["成交额"][i]
            amplitude = stock_data["振幅"][i]
            Chg = stock_data["涨跌幅"][i]
            change_amount = stock_data["涨跌额"][i]
            turnover_rate = stock_data["换手率"][i]

            StockDetail.objects.create(code=code, date=date, open=open, close=close, high=high, low=low,
                                       turnover=turnover, volume=volume, amplitude=amplitude, Chg=Chg,
                                       change_amount=change_amount, turnover_rate=turnover_rate)
    else:
        print("数据库已有股票详细数据")
    res = []
    stock_data_df = StockDetail.objects.filter(code=code)
    for stock in stock_data_df:
        res.append({"value": stock.close, "date": stock.date.strftime("%Y-%m-%d")})

    for i in range(5):
        x = res[-10:]  # 从获取前十天的数据
        x = np.array([i["value"] for i in x])
        predict_date = time.localtime(time.time() + 86400 * i)
        res.append({"value": _predict(x, w_lstm, w_nlp, w_srl), "date": time.strftime("%Y-%m-%d", predict_date)})

    return res[-15:]


def srl_predict(x):
    rnn = RNN(10)
    rnn.load_state_dict(torch.load('stock/model/srl_model.bin'))
    x_hat = np.mean(x)
    x_std = np.std(x)
    input_data = (x - x_hat) / x_std
    output = rnn(torch.unsqueeze(torch.Tensor(input_data), dim=0))
    output_value = torch.squeeze(output).cpu().detach().numpy()
    prediction = x_hat + output_value
    return prediction


def lstm_predict(x):
    # 输入的维度为1，只有Close收盘价
    input_dim = 1
    # 隐藏层特征的维度
    hidden_dim = 32
    # 循环的layers
    num_layers = 2
    # 预测后一天的收盘价
    output_dim = 1

    lstm = LSTM(input_dim=input_dim, hidden_dim=hidden_dim, output_dim=output_dim, num_layers=num_layers)
    lstm.load_state_dict(torch.load('stock/model/lstm_model.bin'))

    x_hat = np.mean(x)
    x_std = np.std(x)
    input_data = (x - x_hat) / x_std
    output = lstm(torch.unsqueeze(torch.Tensor(input_data), dim=0).view(-1, len(input_data), 1))
    # output = lstm(torch.Tensor(input_data))

    output_value = torch.squeeze(output).cpu().detach().numpy()
    prediction = x_hat + output_value
    return prediction


def calculate(number):
    data = xlrd.open_workbook('stock/dataset/{}.xls'.format(number))
    table = data.sheets()[0]
    comments = table.col_values(0)  # 读表格的第一列（评论）

    # 计算情绪值
    sums = []
    for comment in comments:
        sums.append(SnowNLP(comment).sentiments)
    sum = 0
    for each in sums:
        sum += float(each)
    ave = sum / len(comments)  # 计算平均值
    return ave


def nlp_predict(x):
    ave = calculate("300269")  # 计算情绪值，并返回平均值
    res = x.mean() + (ave - 0.5) * 10
    return res


def _predict(x, w_lstm, w_nlp, w_srl):
    return w_lstm * lstm_predict(x) + w_nlp * nlp_predict(x) + w_srl * srl_predict(x)


# Create your views here.


@csrf_exempt
def comprehensive(request):
    json_str = request.body
    json_dict = json.loads(json_str)
    code = json_dict.get("code", None)
    w_lstm = float(json_dict.get("w_lstm", 1 / 3))
    w_nlp = float(json_dict.get("w_nlp", 1 / 3))
    w_srl = float(json_dict.get("w_srl", 1 / 3))
    w_sum = w_lstm + w_nlp + w_srl
    w_lstm = w_lstm / w_sum
    w_nlp = w_nlp / w_sum
    w_srl = w_srl / w_sum

    if Stock.objects.filter(code=code).exists():
        data = predict_stock(code, w_lstm, w_nlp, w_srl)
    else:
        data = predict_stock("600519", w_lstm, w_nlp, w_srl)
    return JsonResponse({'code': 200, 'msg': 'success', 'data': data})
